package com.swallow.auth.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;

/**
 * @author: yangjie.deng@resico.cn
 * @since: 2024-04-01 11:22:06
 * @version: v1.0.0
 * @describe: 通用线程池
 */
@Slf4j
public class CustomerFuture {
    private static volatile ExecutorService executor;


    public static ExecutorService getInstance() {
        if (executor == null) {
            synchronized (CustomerFuture.class) {
                if (executor == null) {
                    var factory = Thread.ofVirtual()
                                        .name("biz-virtual-thread#", 1)
                                        .factory();

                    executor = Executors.newThreadPerTaskExecutor(factory);
                }
            }
        }
        return executor;
    }

    /**
     *  无返回值异步执行线程池
     *
     * @param runnable 执行Runnable接口
     * @return         CompletableFuture<Void>
     */
    public static CompletableFuture<Void> runAsync(Runnable runnable) {
        String traceId = mdc();
        return CompletableFuture.runAsync(() -> {
                                  MDC.put(TRACE_ID, traceId);
                                    try {
                                        runnable.run();
                                    } finally {
                                        MDC.remove(TRACE_ID);
                                    }
                                }, getInstance())
                                .exceptionally(ex -> {
                                                  log.error("异步线程执行过程异常.", ex);
                                                  throw new RuntimeException(ex.getMessage());
                                              }
                                );
    }


    private static final String TRACE_ID = "trace-id";

    private static String mdc() {
        return MDC.get(TRACE_ID);
    }

    /**
     *  带有返回值异步执行
     *
     * @param supplier  执行对象
     * @return          执行结果
     * @param <T>       返回值类型
     */
    public static <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier) {
        String traceId = mdc();
        return CompletableFuture.supplyAsync(() -> {
                                    MDC.put(TRACE_ID, traceId);
                                    try {
                                        return supplier.get();
                                    } finally {
                                        MDC.remove(TRACE_ID);
                                    }
                                }, getInstance())
                                .exceptionally(ex -> {
                                                          log.error("异步线程执行过程异常.", ex);
                                                          throw new RuntimeException(ex.getMessage());
                                                      }
                                );
    }
}
